package com.leetcode.linkedlist;

import com.leetcode.datastructure.ListNode;

import java.util.HashSet;

/**
 * @author: ZhouBert
 * @date: 2019/10/8
 * @description: 141. 环形链表
 * A
 * 给定一个链表，判断链表中是否有环。
 * <p>
 * 为了表示给定链表中的环，我们使用整数 pos 来表示链表尾连接到链表中的位置（索引从 0 开始）。 如果 pos 是 -1，则在该链表中没有环。
 * <p>
 * 示例 1：
 * 输入：head = [3,2,0,-4], pos = 1
 * 输出：true
 * 解释：链表中有一个环，其尾部连接到第二个节点。
 * <p>
 * 示例 2：
 * 输入：head = [1,2], pos = 0
 * 输出：true
 * 解释：链表中有一个环，其尾部连接到第一个节点。
 * <p>
 * 示例 3：
 * 输入：head = [1], pos = -1
 * 输出：false
 * 解释：链表中没有环。
 * <p>
 * 进阶：
 * <p>
 * 你能用 O(1)（即，常量）内存解决此问题吗？
 * <p>
 * 来源：力扣（LeetCode）
 * 链接：https://leetcode-cn.com/problems/linked-list-cycle
 * 著作权归领扣网络所有。商业转载请联系官方授权，非商业转载请注明出处。
 */
public class HasCycle141 {

	/**
	 * todo:需要知道的隐藏信息：非环形链表必然有尾节点！
	 * 1.通过 hash 记录节点-hasCycleByHash--Time[O(n)],Space[O(n)]---6ms 25%
	 * 2.通过 双指针 （追及问题） ，如果是环形必然会相遇-hasCycleByTwoPoint--Time[O(n)],Space[O(1)]
	 *
	 * @param head
	 * @return
	 */
	public static boolean hasCycleByHash(ListNode head) {
		if (head == null) {
			return false;
		}

		ListNode cur=head;
		///利用 哈希表 判断重复
		HashSet<ListNode> set = new HashSet<>();
		while (cur!=null){
			if (set.contains(cur)){
				return true;
			}
			set.add(cur);
			cur=cur.next;
		}
		return false;
	}

	/**
	 * 1ms 86%
	 * @param head
	 * @return
	 */
	public static boolean hasCycleByTwoPoint(ListNode head){
		if (head == null) {
			return false;
		}

		ListNode fp=head;
		ListNode sp=head;
		while (fp!=null&&fp.next!=null){
			fp=fp.next.next;
			sp=sp.next;
			if(sp.equals(fp)){
				return true;
			}
		}
		return false;
	}

	public static void main(String[] args) {

	}
}
